package com.skivingcloud.apiplatform.client;

import cn.hutool.json.JSONUtil;
import com.skivingcloud.admin.conf.HttpsClientRequestFactory;
import com.skivingcloud.apiplatform.signature.annotation.SignedIgnore;
import com.skivingcloud.apiplatform.signature.entity.SignedParam;
import com.skivingcloud.apiplatform.signature.exception.SignedException;
import com.skivingcloud.apiplatform.signature.util.SmCryptoUtils;
import com.skivingcloud.common.utils.R;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.lang.reflect.Field;
import java.util.*;

public class ClientExample {
    /**
     * sm2加密方式例子
     * @throws IllegalAccessException
     */
    public void testSm2() throws IllegalAccessException {

        SignedParam signedParam = getSignedParam();
        signedParam.setAppId("test-sm2");
        //  按照ASCII对map进行排序
        Map map = object2Map(signedParam);
        SortedMap<String, Object> sortedMap = new TreeMap(map);
        String signature = SmCryptoUtils.encrypt2Data("04267fb31247bd03530f3a430a6ecad6871a4c04d2d6c21be479a544675b06ef261de86d509de7a75021124eb639c33e79ba49b4908aa350e20e9582414ff5e297", JSONUtil.toJsonStr(sortedMap));
        signedParam.setSignature(signature);
        //利用restTemplate调用
        RestTemplate restTemplate = new RestTemplate(simpleClientHttpRequestFactory());
        ResponseEntity<Map> res = restTemplate.postForEntity("http://localhost:8703/api/apiplantform/api/example/testExample", signedParam, Map.class);
        System.out.println(signedParam.getAppId() + ":" + res.toString());
    }

    /**
     * sm3加密方式例子
     * @throws IllegalAccessException
     */
    public void testSm3() throws IllegalAccessException {
        SignedParam signedParam = getSignedParam();
        signedParam.setAppId("test-sm3");
        //  按照ASCII对map进行排序
        Map map = object2Map(signedParam);
        SortedMap<String, Object> sortedMap = new TreeMap(map);
        String signature = SmCryptoUtils.encrypt3Data("eu9jep77zpgrdp5uip2133sj13ghrwjc", JSONUtil.toJsonStr(sortedMap));
        signedParam.setSignature(signature);
        sendByRestTemplate(signedParam);
    }

    /**
     * Sm4加密方式例子
     * @throws IllegalAccessException
     */
    public void testSm4() throws IllegalAccessException {
        SignedParam signedParam = getSignedParam();
        signedParam.setAppId("test-sm4");
        //  按照ASCII对map进行排序
        Map map = object2Map(signedParam);
        SortedMap<String, Object> sortedMap = new TreeMap(map);
        String signature = SmCryptoUtils.encrypt4Data("6z4q0auypsl0qya1", JSONUtil.toJsonStr(sortedMap));
        signedParam.setSignature(signature);
        sendByRestTemplate(signedParam);
    }

    /**
     * AES128加密方式例子
     * @throws IllegalAccessException
     */
    public void testAES128() throws IllegalAccessException {
        SignedParam signedParam = getSignedParam();
        signedParam.setAppId("test-aes128");
        //  按照ASCII对map进行排序
        Map map = object2Map(signedParam);
        SortedMap<String, Object> sortedMap = new TreeMap(map);
        String signature = SmCryptoUtils.encryptAES128("j8oaoeh4g96q8ics", JSONUtil.toJsonStr(sortedMap));
        signedParam.setSignature(signature);
        sendByRestTemplate(signedParam);
    }

    /**
     * AES256加密方式例子
     * @throws IllegalAccessException
     */
    public void testAES256() throws IllegalAccessException {
        SignedParam signedParam = getSignedParam();
        signedParam.setAppId("test-aes256");
        //  按照ASCII对map进行排序
        Map map = object2Map(signedParam);
        SortedMap<String, Object> sortedMap = new TreeMap(map);
        String signature = SmCryptoUtils.encryptAES256("h48l91fwz7awejrndta8tx4cm5eloqgb", JSONUtil.toJsonStr(sortedMap));
        signedParam.setSignature(signature);
        sendByRestTemplate(signedParam);
    }

    /**
     * MD5加密方式例子
     * @throws IllegalAccessException
     */
    public void testMD5() throws IllegalAccessException {
        SignedParam signedParam = getSignedParam();
        signedParam.setAppId("test-md5");
        //  按照ASCII对map进行排序
        Map map = object2Map(signedParam);
        SortedMap<String, Object> sortedMap = new TreeMap(map);
        String signature = SmCryptoUtils.encryptMD5("ww4z4vch9ruv2sfe1ah49p6yvne3jq5z", JSONUtil.toJsonStr(sortedMap));
        signedParam.setSignature(signature);
        sendByRestTemplate(signedParam);
    }

    /**
     * SHA256加密方式例子
     * @throws IllegalAccessException
     */
    public void testSHA256() throws IllegalAccessException {
        SignedParam signedParam = getSignedParam();
        signedParam.setAppId("test-sha256");
        //  按照ASCII对map进行排序
        Map map = object2Map(signedParam);
        SortedMap<String, Object> sortedMap = new TreeMap(map);
        String signature = SmCryptoUtils.encryptSHA256("tu3rxrhn19bod8b8eg4xfnnygbhc5urt", JSONUtil.toJsonStr(sortedMap));
        signedParam.setSignature(signature);
        sendByRestTemplate(signedParam);
    }

    /**
     * SHA256加密方式例子
     * @throws IllegalAccessException
     */
    public void testSHA512() throws IllegalAccessException {
        SignedParam signedParam = getSignedParam();
        signedParam.setAppId("test-sha512");
        //  按照ASCII对map进行排序
        Map map = object2Map(signedParam);
        SortedMap<String, Object> sortedMap = new TreeMap(map);
        String signature = SmCryptoUtils.encryptSHA512("abni88kla73zgm3p7s92rmcq49s12x3y", JSONUtil.toJsonStr(sortedMap));
        signedParam.setSignature(signature);
        sendByRestTemplate(signedParam);
    }

    /**
     * RSA加密方式例子
     * @throws IllegalAccessException
     */
    public void testRsa() throws IllegalAccessException {
        SignedParam signedParam = getSignedParam();
        signedParam.setAppId("test-rsa");
        //  按照ASCII对map进行排序
        Map map = object2Map(signedParam);
        SortedMap<String, Object> sortedMap = new TreeMap(map);
        String signature = SmCryptoUtils.encryptRsa("30819f300d06092a864886f70d010101050003818d003081890281810096146902f9e5083ef64e7161d113f7fe6406aedc6111de11091510b5edc50ebb83ab982cbda99366f1466ca1bf528225b3a876e787b78b71e3de7a5df98511d8596f4fdb283a517ca5049b5cb985ebe04e6ec45ea5bd36f94fe119fa5d734a6f575e85bfe599d8e433f526e8790a0f40134618a72032f0e8e79a94a0146975970203010001", JSONUtil.toJsonStr(sortedMap));
        signedParam.setSignature(signature);
        sendByRestTemplate(signedParam);
    }

    public SignedParam getSignedParam(){
        ApiDataExample data = new ApiDataExample("姓名", "女", "13838389438", "test@test.com.cn");
        SignedParam signedParam = new SignedParam();
//        signedParam.setAppId("test-sm2");
        signedParam.setData(JSONUtil.toJsonStr(data));
        signedParam.setTimestamp(System.currentTimeMillis() / 1000);
        signedParam.setNonce(new Random().nextInt());
        return signedParam;
    }

    /**
     * 利用restTemplate调用
     * @param signedParam
     */
    public void sendByRestTemplate(SignedParam signedParam){
        //利用restTemplate调用
        RestTemplate restTemplate = new RestTemplate(simpleClientHttpRequestFactory());
        ResponseEntity<R> res = restTemplate.postForEntity("http://localhost:8703/api/apiplantform/api/example/testExample", signedParam, R.class);
        System.out.println(signedParam.getAppId() + ":" + res.toString());
    }
    public Map<String, Object> object2Map(Object obj) throws IllegalAccessException {
        Map<String, Object> map = new HashMap();
        if (obj == null) {
            return map;
        }
        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            //  If the field is not ignored, put it in the map
            //  If the field is null, throw an exception
            SignedIgnore signedIgnore = AnnotationUtils.findAnnotation(field, SignedIgnore.class);
            if (signedIgnore == null) {
                if (field.get(obj) == null) {
                    throw new SignedException.NullParam(field.getName());
                }
                map.put(field.getName(), field.get(obj));
            }
        }
        return map;
    }

    public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
        // 创建一个 httpCilent 简单工厂
        HttpsClientRequestFactory factory = new HttpsClientRequestFactory();
        // 设置连接超时
        factory.setConnectTimeout(60*1000);
        // 设置读取超时
        factory.setReadTimeout(60*1000);
        return factory;
    }

    public static void main(String[] args){
        ClientExample example = new ClientExample();
        try {
            example.testSm2();
            example.testSm3();
            example.testSm4();
            example.testAES128();
//            example.testAES256();
            example.testMD5();
            example.testSHA256();
            example.testSHA512();
            example.testRsa();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
